package com.hjtech.inject;

/*
 * 项目名:    InjectTest
 * 包名       com.hjtech.inject
 * 文件名:    Utils
 * 创建者:    ZJB
 * 创建时间:  2017/10/26 on 17:05
 * 描述:     TODO
 */

import android.app.Activity;
import android.util.Log;
import android.view.View;

import com.hjtech.inject.annotation.EventType;
import com.hjtech.inject.annotation.InjectView;
import com.hjtech.inject.annotation.onClick;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Utils {

    public static final String TAG = "ProxyTest";

    public static void injectEvent(Activity activity) {
        if (null == activity) {
            return;
        }
        //获取activity的class对象
        Class<? extends Activity> activityClass = activity.getClass();
        //获取activity中的所有方法
        Method[] declaredMethods = activityClass.getDeclaredMethods();
        //遍历所有方法
        for (Method method : declaredMethods) {
            //判断方法中是否有onClick注解
            if (method.isAnnotationPresent(onClick.class)) {
                Log.i(Utils.TAG, method.getName());
                //获取方法中的onClick注解
                onClick annotation = method.getAnnotation(onClick.class);
                //获取onClick注解中的（id）值
                int[] value = annotation.value();
                //获取onclick注中的EventType注解
                EventType eventType = annotation.annotationType().getAnnotation(EventType.class);
                //获取EventType注解中的属性值
                Class listenerType = eventType.listenerType();
                String listenerSetter = eventType.listenerSetter();
                String methodName = eventType.methodName();

                //创建InvocationHandler和动态代理(代理要实现listenerType，这个例子就是处理onClick点击事件)
                ProxyHandler proxyHandler = new ProxyHandler(activity);
                Object listener = Proxy.newProxyInstance(listenerType.getClassLoader(), new Class[]{listenerType}, proxyHandler);

                proxyHandler.mapMethod(methodName, method);
                try {
                    //遍历所有id
                    for (int id : value) {
                        //反射获取activity中的findViewById方法
                        Method findViewByIdMethod = activityClass.getMethod("findViewById", int.class);
                        //设置权限
                        findViewByIdMethod.setAccessible(true);
                        //反射调用在activity中findViewById的方法。传入id参数。返回view对象
                        View btn = (View) findViewByIdMethod.invoke(activity, id);
                        //根据listenerSetter方法名和listenerType方法参数在btn（View）中找到对应的method
                        Method listenerSetMethod = btn.getClass().getMethod(listenerSetter, listenerType);
                        //设置权限
                        listenerSetMethod.setAccessible(true);
                        //反射调用对应btn（View）中的setOnClickListener方法，传入代理listener
                        listenerSetMethod.invoke(btn, listener);
                    }

                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }
    }


    public static void injectView(Activity activity) {
        if (null == activity) {
            return;
        }
        //获取activity的class对象
        Class<? extends Activity> activityClass = activity.getClass();
        //获取activity中的所有属性
        Field[] declaredFields = activityClass.getDeclaredFields();
        //遍历属性
        for (Field field : declaredFields) {
            //如果属性中有InjectView注解
            if (field.isAnnotationPresent(InjectView.class)) {
                //获取属性中的InjectView注解
                InjectView annotation = field.getAnnotation(InjectView.class);
                //获取注解中的值（id值）
                int value = annotation.value();

                try {
                    //获取activity中的findViewById方法，参数是Int
                    Method findViewByIdMethod = activityClass.getMethod("findViewById", int.class);
                    //设置方法访问权限
                    findViewByIdMethod.setAccessible(true);
                    //再activity中执行findViewById方法，id为注解获取的值，返回具体的对象
                    Object invoke = findViewByIdMethod.invoke(activity, value);
                    //在activity中将对象放到对应的属性当中
                    field.set(activity, invoke);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }


            }
        }

    }
}
